home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cubezip.exe
/
CUBE.ASM
next >
Wrap
Assembly Source File
|
1991-10-15
|
30KB
|
609 lines
include macros.h
;╒══════════════════════════════════════════════════════════════════════════╕
;│ │
;│ CUBE - A general purpose solver of combinatorial block puzzles │
;│ │
;│ written by: Steve Gibson │
;│ Gibson Research Corporation │
;│ 9/18/91 │
;│ │
;│ Please note: These files were asssembled and linked with Steve │
;│ Russell's excellent optimizing assembler (OPTASM) and linker │
;│ (OPTLINK). Consequently, if any "conditional jump out-of-range" │
;│ errors are received either the files will have to be edited or │
;│ an optimizing assembler will have to be used. │
;│ - ENJOY! │
;│ │
;╘══════════════════════════════════════════════════════════════════════════╛
TITLE CUBE
;╒══════════════════════════════════════════════════════════════════════════╕
;│ │
;│ CUBE solves Bob's wooden block puzzle. │
;│ │
;│ ──────────────────────────────────────────────────────────────── │
;│ Please see the READ.ME and TECHTALK.TXT files that were included │
;│ within the CUBE.EXE self-extracting ZIP file for further details │
;│ about the CUBE ... and for information about where you can │
;│ purchase the cube puzzle if you'd like to play with it yourself │
;│ and assemble it from the program's result. │
;│ ──────────────────────────────────────────────────────────────── │
;│ │
;│ This puzzle consists of a 3x3x3 "master cube" composed of 27 │
;│ "sub-cubes." Combinations of sub-cubes are stuck together │
;│ forming the nine puzzle pieces. The puzzle is complicated │
;│ by the fact that a number of the sub-cubes are cut half, with │
;│ different halves stuck to different pieces. This means that │
;│ rotating the pieces requires both rotation and translation of │
;│ the sub-cubes, rather than just translation as would be the │
;│ case if all of the sub-cubes were simple cubes. │
;│ │
;│ Numbering and Axis legend: │
;│ ───────────────────────────────────────────────────────────── │
;│ Individual pieces are numbered 0 thru 8. │
;│ Positions within the master 3x3x3 cube are numbered 1 thru 27. │
;│ Corners of the 2x2x2 sub-cubes are numbered 1 thru 8. │
;│ The X axis runs left-to-right through the master cube. │
;│ The Y axis runs into and outof the table. │
;│ The Z axis runs forward and backward through the master cube. │
;│ A positive X rotation flops the cube forward. │
;│ A positive Y rotation twists the cube 90 degrees clockwise. │
;│ A positive Z rotation flops the cube to the right. │
;│ │
;╘══════════════════════════════════════════════════════════════════════════╛
;┌──────────────────────────────────────────────────────────────────────────┐
;│ **************** E Q U A T E S A N D M A C R O S *************** │
;└──────────────────────────────────────────────────────────────────────────┘
NUMBER_OF_PIECES equ 9 ; puzzle contains nine pieces
CUBE_LENGTH equ 3
CUBE_HEIGHT equ 3
CUBE_DEPTH equ 3
CUBE_SURFACE equ CUBE_LENGTH * CUBE_HEIGHT
SUB_CUBE_COUNT equ CUBE_LENGTH * CUBE_HEIGHT * CUBE_DEPTH
PIECE_DEFINITION_LENGTH equ (OFFSET Piece_2 - OFFSET Piece_1)
;┌──────────────────────────────────────────────────────────────────────────┐
;│ *************************** S E G M E N T S ************************** │
;└──────────────────────────────────────────────────────────────────────────┘
CodeSeg segment para public 'code'
assume cs: CodeSeg, ds: CodeSeg, es: CodeSeg, ss: CodeSeg
;┌──────────────────────────────────────────────────────────────────────────┐
;│ *********************** E N T R Y P O I N T *********************** │
;└──────────────────────────────────────────────────────────────────────────┘
org 0
StartOfProg equ THIS BYTE
org 100h
Entry: jmp SolveIt
;┌──────────────────────────────────────────────────────────────────────────┐
;│ ***************** P U Z Z L E P I E C E D A T A **************** │
;└──────────────────────────────────────────────────────────────────────────┘
PieceDefinitions:
;┌──────────────────────────────────────────────────────────────────────────┐
;│ The piece definitions specify the shape of the individual │
;│ pieces, and their initial position parity. Each of the first │
;│ five bytes represents a single sub-cube, with each of the │
;│ byte's 8-bits representing wood in the respective corner of │
;│ the sub-cube. Thus FF represents a solid cube and AA, CC, │
;│ and F0 represents various orientations of half-cubes. ZERO │
;│ parity means Dark Wood at the 1,1,1 corner (the first byte) │
;│ of the cube's definition. │
;│──────────────────────────────────────────────────────────────────────────│
;│ 1 2 3 4 5 6 Color Parity │
;└──────────────────────────────────────────────────────────────────────────┘
Piece_1 db 0FFh, 0FFh, 0FFh, 0CCh, 000h, 000h, 0 ; L: short foot
Piece_2 db 0FFh, 0FFh, 0AAh, 000h, 000h, 0AAh, 0 ; short L with thin foot
Piece_3 db 0FFh, 0FFh, 000h, 0FFh, 000h, 000h, 0 ; elbow 1
Piece_4 db 0FFh, 0FFh, 000h, 0FFh, 000h, 000h, 1 ; elbow 2
Piece_5 db 0FFh, 0FFh, 0AAh, 00Fh, 000h, 000h, 0 ; short L with twisted foot
Piece_6 db 0FFh, 0FFh, 00Fh, 0CCh, 000h, 000h, 0 ; L: twist head & short foot
Piece_7 db 0FFh, 0FFh, 00Fh, 000h, 000h, 000h, 1 ; I: twisted head
Piece_8 db 0FFh, 0FFh, 0F0h, 0CCh, 000h, 000h, 0 ; L: lifted twist hd, shrt ft
Piece_9 db 0FFh, 0FFh, 0CCh, 000h, 0F0h, 000h, 0 ; T: twist head, lifted stem
;┌──────────────────────────────────────────────────────────────────────────┐
;│ These Spin Tables manage the rotation of the 2x2x2 sub-cubes │
;│ within the larger 3x3x3 master cube. Each sub-cube contains │
;│ eight items, representing wood in each of its eight corners. │
;│ Each table consists of 8 bytes, where the ON bit in the byte │
;│ specifies where the bit mapped into the byte will move when │
;│ the 2x2x2 cube is subjected to a positive rotation about the │
;│ specified axis. │
;│ │
;│ Destination: 12345678 12345678 12345678 12345678 │
;└──────────────────────────────────────────────────────────────────────────┘
Spin_X_Table db 00001000b, 00000100b, 10000000b, 01000000b
db 00000010b, 00000001b, 00100000b, 00010000b
;────────────────────────────────────────────────────────────────────────────
Spin_Y_Table db 01000000b, 00010000b, 10000000b, 00100000b
db 00000100b, 00000001b, 00001000b, 00000010b
;────────────────────────────────────────────────────────────────────────────
Spin_Z_Table db 01000000b, 00000100b, 00010000b, 00000001b
db 10000000b, 00001000b, 00100000b, 00000010b
;┌──────────────────────────────────────────────────────────────────────────┐
;│ These Rotate Tables manage the translation of the 2x2x2 │
;│ sub-cubes within the larger 3x3x3 master cube. When the │
;│ master cube is rotated each of the sub-cubes is rotated │
;│ based upon the Spin tables above, then the sub-cube is │
;│ translated, relocating its position within the 3x3x3 master │
;│ cube. Each entry in the table below specifies which one of │
;│ the 27 sub-cubes will occupy the respective location │
;│ within the new master cube after rotation. │
;└──────────────────────────────────────────────────────────────────────────┘
Rotate_X_Table db 7, 8, 9, 16, 17, 18, 25, 26, 27 ; 1- 9
db 4, 5, 6, 13, 14, 15, 22, 23, 24 ; 10-18
db 1, 2, 3, 10, 11, 12, 19, 20, 21 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Rotate_Y_Table db 7, 4, 1, 8, 5, 2, 9, 6, 3 ; 1- 9
db 16, 13, 10, 17, 14, 11, 18, 15, 12 ; 10-18
db 25, 22, 19, 26, 23, 20, 27, 24, 21 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Rotate_Z_Table db 19, 10, 1, 22, 13, 4, 25, 16, 7 ; 1- 9
db 20, 11, 2, 23, 14, 5, 26, 17, 8 ; 10-18
db 21, 12, 3, 24, 15, 6, 27, 18, 9 ; 19-27
;┌──────────────────────────────────────────────────────────────────────────┐
;│ These Translation Tables manage the translation of the sub-cubes │
;│ within the larger 3x3x3 master cube. When the master cube is │
;│ translated, each of the sub-cubes is relocated within the 3x3x3 │
;│ master cube. Each entry in the table below specifies which one of │
;│ the 27 sub-cubes will occupy the respective location within the │
;│ new master cube after translation. A ZERO entry means that the │
;│ location will be completely empty after translation. │
;└──────────────────────────────────────────────────────────────────────────┘
Translate_X0_Table db 2, 3, 0, 5, 6, 0, 8, 9, 0 ; 1- 9
db 11, 12, 0, 14, 15, 0, 17, 18, 0 ; 10-18
db 20, 21, 0, 23, 24, 0, 26, 27, 0 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Translate_X1_Table db 0, 1, 2, 0, 4, 5, 0, 7, 8 ; 1- 9
db 0, 10, 11, 0, 13, 14, 0, 16, 17 ; 10-18
db 0, 19, 20, 0, 22, 23, 0, 25, 26 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Translate_Y0_Table db 10, 11, 12, 13, 14, 15, 16, 17, 18 ; 1- 9
db 19, 20, 21, 22, 23, 24, 25, 26, 27 ; 10-18
db 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Translate_Y1_Table db 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 1- 9
db 1, 2, 3, 4, 5, 6, 7, 8, 9 ; 10-18
db 10, 11, 12, 13, 14, 15, 16, 17, 18 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Translate_Z0_Table db 4, 5, 6, 7, 8, 9, 0, 0, 0 ; 1- 9
db 13, 14, 15, 16, 17, 18, 0, 0, 0 ; 10-18
db 22, 23, 24, 25, 26, 27, 0, 0, 0 ; 19-27
;────────────────────────────────────────────────────────────────────────────
Translate_Z1_Table db 0, 0, 0, 1, 2, 3, 4, 5, 6 ; 1- 9
db 0, 0, 0, 10, 11, 12, 13, 14, 15 ; 10-18
db 0, 0, 0, 19, 20, 21, 22, 23, 24 ; 19-27
;┌──────────────────────────────────────────────────────────────────────────┐
;│ These Surface Tables specify which sub-cubes lie upon each of the │
;│ six surfaces of the master cube. This is used by the translation │
;│ logic to determine whether an object may be translated into the │
;│ empty surface of the master cube. Each table lists the nine sub- │
;│ cubes lying on the respecting face of the master cube. │
;└──────────────────────────────────────────────────────────────────────────┘
Surface_X0_Table db 1, 4, 7, 10, 13, 16, 19, 22, 25
Surface_X1_Table db 3, 6, 9, 12, 15, 18, 21, 24, 27
;────────────────────────────────────────────────────────────────────────────
Surface_Y0_Table db 1, 2, 3, 4, 5, 6, 7, 8, 9
Surface_Y1_Table db 19, 20, 21, 22, 23, 24, 25, 26, 27
;────────────────────────────────────────────────────────────────────────────
Surface_Z0_Table db 1, 2, 3, 10, 11, 12, 19, 20, 21
Surface_Z1_Table db 7, 8, 9, 16, 17, 18, 25, 26, 27
;┌──────────────────────────────────────────────────────────────────────────┐
;│ ************ M I S C E L L A N E O U S V A R I A B L E S ************ │
;└──────────────────────────────────────────────────────────────────────────┘
;┌──────────────────────────────────────────────────────────────────────────┐
;│ Indexed by piece number [0..8] This is a table of the number of images │
;│ we've generated for each piece. The image generator increments these │
;│ values as it stores non-redundant piece images, and the tree exploring │
;│ routine uses this to explore the resulting image tables. │
;└──────────────────────────────────────────────────────────────────────────┘
PieceImageCounts dw NUMBER_OF_PIECES dup (0)
;┌──────────────────────────────────────────────────────────────────────────┐
;│ Indexed by piece number [0..8] This is a table of OFFSETS into the │
;│ PieceTable (but relative to DS) for each set of piece image tables. │
;└──────────────────────────────────────────────────────────────────────────┘
PieceTableOffsets dw NUMBER_OF_PIECES dup (0)
;┌──────────────────────────────────────────────────────────────────────────┐
;│ This is the offset of the NEXT AVAILABLE BYTE in the PieceTable. │
;│ Piece image tables are allocated from this point and it is augmented │
;│ by the size of a table: SUB_CUBE_COUNT+1. │
;└──────────────────────────────────────────────────────────────────────────┘
CurrentTableBase dw PieceTable ; initialize at bottom
;┌──────────────────────────────────────────────────────────────────────────┐
;│ These are general usage working piece storage tables. The Working │
;│ Piece Table contains the piece position we're currently operating upon. │
;└──────────────────────────────────────────────────────────────────────────┘
WorkingPieceTable db SUB_CUBE_COUNT+1 dup(0)
TempPieceTable db SUB_CUBE_COUNT+1 dup(0)
XSaveTable db SUB_CUBE_COUNT+1 dup(0)
YSaveTable db SUB_CUBE_COUNT+1 dup(0)
;┌──────────────────────────────────────────────────────────────────────────┐
;│ The number of the Piece we're currently operating upon. │
;└──────────────────────────────────────────────────────────────────────────┘
CurrentPiece dw 0
;┌──────────────────────────────────────────────────────────────────────────┐
;│ ********** S T A R T O F E X E C U T A B L E C O D E ********** │
;└──────────────────────────────────────────────────────────────────────────┘
SolveIt: cld ; initialize things ...
mov sp, OFFSET TopOfStack ; switch to internal stack
call SetupTheSystem
mov CurrentPiece, 0 ; start with the first one
;┌──────────────────────────────────────────────────────────────────────────┐
;│ We build all possible positions of each puzzle piece ... This is all │
;│ 24 orientations of each the piece in each translated location. │
;└──────────────────────────────────────────────────────────────────────────┘
;┌──────────────────────────────────────────────────────────────────────────┐
;│ To process a piece, we load the piece's definition into the │
;│ WorkingTable, then give it a good spin! │
;└──────────────────────────────────────────────────────────────────────────┘
ProcessAPiece: mov ax, PIECE_DEFINITION_LENGTH ; don't move parity
mov bx, CurrentPiece
mov cx, ax ; save the length for the move
dec cx ; move one less than the len
mul bx ; get piece definition
add ax, OFFSET PieceDefinitions
mov si, ax
mov di, OFFSET WorkingPieceTable
rep movsb ; load the table
zero al
mov cx, SUB_CUBE_COUNT - (PIECE_DEFINITION_LENGTH - 1)
rep stosb ; and clear the rest
movsb ; add the parity to the end
;┌──────────────────────────────────────────────────────────────────────────┐
;│ Now we save the CurrentTableBase as the base for this piece │
;└──────────────────────────────────────────────────────────────────────────┘
double bx ; turn piece into a word ptr
mov ax, CurrentTableBase
mov PieceTableOffsets[bx], ax
mov PieceImageCounts[bx], 0 ; clear the count
;┌──────────────────────────────────────────────────────────────────────────┐
;│ Now we store all 24 orientations of the piece in every │
;│ translation. The sequence of orientation explorations is: │
;│ 3*(3*Y,X) -<Y,X,X>- 3*(3*Y,X) │
;└──────────────────────────────────────────────────────────────────────────┘
call ExploreHalf ; flesh out half the orientations
call Rotate_Y ; flip over to the second half
call Rotate_X_Twice
call ExploreHalf ; and flesh out the second half
;┌──────────────────────────────────────────────────────────────────────────┐
;│ Now we process the next piece ... if one exists │
;└──────────────────────────────────────────────────────────────────────────┘
inc CurrentPiece ; [0..8]
cmp CurrentPiece, NUMBER_OF_PIECES
jb ProcessAPiece
;┌──────────────────────────────────────────────────────────────────────────┐
;│ No more pieces! ... so let's get to work! │
;│ We'll exhaustively search through the entire tree ... │
;└──────────────────────────────────────────────────────────────────────────┘
jmp SearchTheTree
;╒══════════════════════════════════════════════════════════════════════════╕
;│ ************************ S U B R O U T I N E S *********************** │
;╘══════════════════════════════════════════════════════════════════════════╛
;╒══════════════════════════════════════════════════════════════════════════╕
;│ This routine makes 12 calls to "StoreTranslations" with the │
;│ puzzle piece in a different orientation each time. It's │
;│ called twice, once for each half of the possible orientations. │
;│ The sequence of rotation calls is: 3*(3*Y,X) │
;└──────────────────────────────────────────────────────────────────────────┘
ExploreHalf: mov cx, 3
MiddleLoop: call StoreAllTrans ; store translations @ current orient
push cx
mov cx, 3
;────────────────────────────────────────────────────────────────────────────
InnerLoop: call Rotate_Y
call StoreAllTrans
loop InnerLoop
call Rotate_X
pop cx
loop MiddleLoop
ret
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Given the current orientation of the current WorkingPiece, build legal │
;│ translations, storing unique ones in the piece's position image table. │
;└──────────────────────────────────────────────────────────────────────────┘
StoreAllTrans: push cx
call SlideToOrigin ; push the piece -> X0, Y0, Z0
jmp ExploreX
MoveOnX: call TranslateX1
ExploreX: mov di, OFFSET XSaveTable
call SavePieceState ; stack the piece's location
jmp ExploreY
;════════════════════════════════════════════════════════════════════════════
MoveOnY: call TranslateY1
ExploreY: mov di, OFFSET YSaveTable
call SavePieceState ; stack the piece's location
jmp ExploreZ
;────────────────────────────────────────────────────────────────────────────
MoveOnZ: call TranslateZ1
ExploreZ: test WorkingPieceTable[SUB_CUBE_COUNT], 1 ; check parity
jnz SkipThisSave
call StoreNewPosition
SkipThisSave: mov bx, OFFSET Surface_Z1_Table
call TestSurface
jz MoveOnZ
;────────────────────────────────────────────────────────────────────────────
mov si, OFFSET YSaveTable
call RestorePieceState ; recover the piece's loc.
mov bx, OFFSET Surface_Y1_Table
call TestSurface
jz MoveOnY
;════════════════════════════════════════════════════════════════════════════
mov si, OFFSET XSaveTable
call RestorePieceState ; recover the piece's loc.
mov bx, OFFSET Surface_X1_Table
call TestSurface
jz MoveOnX
pop cx
ret
StoreNewPosition:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Save the unique position (from WorkingPositionTable) into │
;│ the piece's position memory. │
;│ │
;│ ax - overall iteration counter │
;│ bx - destination renewal │
;│ cx - rep count │
;│ dx - rep save │
;│ si source index │
;│ di dest index │
;│ bp - source renewal │
;└──────────────────────────────────────────────────────────────────────────┘
mov bx, CurrentPiece
double bx ; make word index
mov ax, PieceImageCounts[bx] ; get image count
mov bx, PieceTableOffsets[bx] ; get table base
mov bp, OFFSET WorkingPieceTable ; get source index
mov dx, (SUB_CUBE_COUNT+1)/2 ; (14 compares)
;────────────────────────────────────────────────────────────────────────────
CheckForUnique: mov cx, dx ; get the table size to compare
mov si, bp ; renew the source location
mov di, bx ; and get the table loc
check ax ; do we have any more?
jz ItsUnique ; nope, so move rather than compare
repe cmpsw ; are they the same?
je NotUnique
add bx, dx
add bx, dx ; point to the next table
dec ax ; decrement the number remaining
jmp CheckForUnique ; check the next image
;────────────────────────────────────────────────────────────────────────────
ItsUnique: rep movsw ; copy the new position ...
mov CurrentTableBase, di ; update the base pointer
mov bx, CurrentPiece ; get index
double bx ; make word index
inc PieceImageCounts[bx] ; and increment the count
call ShowImageCount
;────────────────────────────────────────────────────────────────────────────
NotUnique: ret
SavePieceState:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Save the WorkingPieceTable piece state │
;│ in the table pointed to by [DI]. │
;└──────────────────────────────────────────────────────────────────────────┘
mov si, OFFSET WorkingPieceTable
jmp CopyPieceTable
RestorePieceState:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Restore the WorkingPieceTable piece state │
;│ from the table pointed to by [SI]. │
;└──────────────────────────────────────────────────────────────────────────┘
mov di, OFFSET WorkingPieceTable
CopyPieceTable: mov cx, (SUB_CUBE_COUNT+1)/2 ; move words
rep movsw
ret
SlideToOrigin:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Translate the current piece as far as it │
;│ will go in the X0, Y0, and Z0 directions. │
;└──────────────────────────────────────────────────────────────────────────┘
SlideXBack: mov bx, OFFSET Surface_X0_Table
call TestSurface
jnz SlideYBack
call TranslateX0
jmp SlideXBack
;────────────────────────────────────────────────────────────────────────────
SlideYBack: mov bx, OFFSET Surface_Y0_Table
call TestSurface
jnz SlideZBack
call TranslateY0
jmp SlideYBack
;────────────────────────────────────────────────────────────────────────────
SlideZBack: mov bx, OFFSET Surface_Z0_Table
call TestSurface
jnz Originated
call TranslateZ0
jmp SlideZBack
;────────────────────────────────────────────────────────────────────────────
Originated: ret
;╒══════════════════════════════════════════════════════════════════════════╕
;│ These entry-points slide the puzzle piece one │
;│ cube in the appropriate direction │
;└──────────────────────────────────────────────────────────────────────────┘
TranslateX0: mov bx, OFFSET Translate_X0_Table
jmp ToggleParity
TranslateX1: mov bx, OFFSET Translate_X1_Table
jmp ToggleParity
TranslateY0: mov bx, OFFSET Translate_Y0_Table
jmp ToggleParity
TranslateY1: mov bx, OFFSET Translate_Y1_Table
jmp ToggleParity
TranslateZ0: mov bx, OFFSET Translate_Z0_Table
jmp ToggleParity
TranslateZ1: mov bx, OFFSET Translate_Z1_Table
jmp ToggleParity
;────────────────────────────────────────────────────────────────────────────
Rotate_X_Twice: Call Rotate_X ; execute below twice
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Flop the WorkingPiece definition forward │
;│ The X axis runs left-to-right through the cube │
;└──────────────────────────────────────────────────────────────────────────┘
Rotate_X: mov bx, OFFSET Spin_X_Table ; the X spin spec
call SpinCubes ; spin individuals
mov bx, OFFSET Rotate_X_Table ; the X rotate spec
jmp MoveCubes
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Twist the WorkingPiece definition clockwise │
;│ The Y axis runs top-to-bottom through the cube │
;└──────────────────────────────────────────────────────────────────────────┘
Rotate_Y: mov bx, OFFSET Spin_Y_Table ; the X spin spec
call SpinCubes ; spin individuals
mov bx, OFFSET Rotate_Y_Table ; the X rotate spec
jmp MoveCubes
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Flop the WorkingPiece definition to the right │
;│ The Z axis runs front-to-back through the cube │
;└──────────────────────────────────────────────────────────────────────────┘
Rotate_Z: mov bx, OFFSET Spin_Z_Table ; the X spin spec
call SpinCubes ; spin individuals
mov bx, OFFSET Rotate_Z_Table ; the X rotate spec
jmp MoveCubes
ToggleParity:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ This entry to MoveCubes toggles the │
;│ parity bit in the WorkingPieceTable │
;└──────────────────────────────────────────────────────────────────────────┘
xor WorkingPieceTable[SUB_CUBE_COUNT], 1 ; toggle bit
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Rotate the WorkingPiece sub-cubes about the central │
;│ axis using the rotation table pointed to by BX │
;└──────────────────────────────────────────────────────────────────────────┘
MoveCubes: push cx
mov cx, SUB_CUBE_COUNT
mov di, OFFSET TempPieceTable
push di ; save temp piece table location
;────────────────────────────────────────────────────────────────────────────
NextCube: mov si, [bx] ; get the item to move
and si, 00FFh ; the index is byte size
mov al, WorkingPieceTable[si-1] ; 0-base it
jnz MoveCube ; did we get a zero?
zero al ; yep, so clear the block...
MoveCube: stosb ; save the new piece definition
inc bx ; point to next table entry
loop NextCube
;────────────────────────────────────────────────────────────────────────────
mov cx, SUB_CUBE_COUNT
pop si ; recover the temp piece location
mov di, OFFSET WorkingPieceTable
rep movsb ; and copy the temp -> piece
pop cx
ret
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Spin the individual WorkingPiece sub-cubes about │
;│ their own axis using the spin table pointed to by BX │
;└──────────────────────────────────────────────────────────────────────────┘
SpinCubes: push cx
mov di, OFFSET WorkingPieceTable
mov cx, SUB_CUBE_COUNT
SpinCorner: push cx ; save cube counter
mov ah, [di] ; get the cube's bits
zero al ; zero result catcher
mov cx, 8 ; spin 8 bits
DoCorner: shl ah, 1 ; get the next bit
jnc NextCorner
or al, [bx] ; or in the bit specified
NextCorner: inc bx ; get next mask
loop DoCorner ; and do eight of them
stosb ; save the result and inc ...
sub bx, 8 ; and re-point BX to the table
pop cx ; recover the cube counter
loop SpinCorner
pop cx
ret
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Test the WorkingPieceTable for "wood" along the surface │
;│ specified in the table pointed to by BX, return with FLAGS │
;└──────────────────────────────────────────────────────────────────────────┘
TestSurface: mov ax, 00FFh ; byte mask
mov cx, CUBE_SURFACE ; nine sub-cubes on surface
;────────────────────────────────────────────────────────────────────────────
NextSubCube: mov si, [bx] ; get the item to move
and si, ax ; the index is only a byte long
test BYTE PTR WorkingPieceTable[si-1], al ; check for wood
jnz SurfaceTested
inc bx ; prepare for the next one
loop NextSubCube
zero cx ; set flags to "ZERO"
SurfaceTested: ret
WaitForKeypress:
;╒══════════════════════════════════════════════════════════════════════════╕
;│ Waits for a keypress from the keyboard ... │
;└──────────────────────────────────────────────────────────────────────────┘
mov ah, GETKEY_WAIT
int KEYBOARD_IO
ret
;────────────────────────────────────────────────────────────────────────────
include cubesys.inc ; include the cube screen file here
include cubesrch.inc ; include the cube search algorithm
;════════════════════════════════════════════════════════════════════════════
InitScreenBuffer = THIS BYTE
PieceTable = InitScreenBuffer + SCREEN_LENGTH
BottomOfStack = PieceTable + (SUB_CUBE_COUNT+1) * (8*72+96)
TopOfStack = BottomOfStack + STACK_DEPTH
;════════════════════════════════════════════════════════════════════════════
CodeSeg ends
end Entry